import 'dart:io';

import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:dio/native_imp.dart';
import 'package:system_proxy/system_proxy.dart';

import '../config/ApiConfig.dart';
import '../config/NetWorkConfig.dart';
import 'core/CacheInterceptors.dart';
import 'core/DioTransFormer.dart';
import 'core/OptionInterceptor.dart';
import 'core/ResponseInterceptor.dart';

CancelToken _cancelToken = CancelToken();

enum DioMethod {
  get,
  post,
  put,
  delete,
  patch,
  head,
}

class DioClient extends DioForNative {
  static DioClient? _instance;

  //工厂单利模式
  factory DioClient() => _instance ??= DioClient._init();

  static get instance => _instance;

  DioClient._init() {
    //重新设置转化器
    /// 添加转换器
    transformer = DioTransFormer();
    //在请求发起前修改头部

    ///请求的Content-Type，默认值是"application/json; charset=utf-8".
    /// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
    // options.contentType=Headers.formUrlEncodedContentType;
    //修改地址
    options = BaseOptions(
        baseUrl: ApiConfig.mainUrl,
        contentType: "application/json; charset=utf-8",
        connectTimeout: NetWorkConfig.connectTimeout,
        receiveTimeout: NetWorkConfig.receiveTimeout,
        sendTimeout: NetWorkConfig.sendTimeout);

    ///注意拦截器起是依次执行---  一般log日志拦截器放在最后
    //处理头部
    interceptors.add(OptionInterceptor());
    //处理回来的数据
    interceptors.add(ResponseInterceptor());
    //处理网络缓存
    //var cookieJar = CookieJar();
    //interceptors.add(CookieManager(cookieJar));

    /// 加缓存拦截器
    interceptors.add(CacheInterceptors());

    interceptors.add(LogInterceptor(responseBody: true,requestBody: true));

    proxy();
  }

  ///get请求
  doGet<T>(path,
      {queryParameters,
      options,
      cancelToken,
      onReceiveProgress,
      String? module}) async {
    if (module != null) {
      options ??= Options();
      options.headers ??= {"moduleCode": module};
      options.headers["moduleCode"] = module;
    }
    try {
      var response = await get<T>(path,
          queryParameters: queryParameters,
          options: options,
          cancelToken: cancelToken ?? _cancelToken,
          onReceiveProgress: onReceiveProgress);
      return response.data;
    } on Exception catch (e) {
      throw e;
    }
  }

  ///post请求
  doPost<T>(path,
      {queryParameters,
      data,
      options,
      cancelToken,
      onSendProgress,
      onReceiveProgress,
      String? module}) async {
    if (module != null) {
      options ??= Options();
      options.headers ??= {"moduleCode": module};
      options.headers["moduleCode"] = module;
    }
    try {
      var response = await post<T>(path,
          queryParameters: queryParameters,
          options: options,
          data: data ?? {},
          cancelToken: cancelToken ?? _cancelToken,
          onSendProgress: onSendProgress,
          onReceiveProgress: onReceiveProgress);
      return response.data;
    } on Exception catch (e) {
      throw e;
    }
  }

  // void uploadFiles(List<String> filePaths, Function callBack, {bool hideLoading = false}) async{
  //   List<String> prePaths = [];
  //   if(filePaths.isEmpty){
  //     callBack(prePaths);
  //     return;
  //   }
  //   int num = 0;
  //   for(int i=0;i<filePaths.length;i++){
  //     String filePath= filePaths[i];
  //     if(filePath == ""){
  //       num++;
  //       if(num == filePaths.length){
  //         callBack(prePaths);
  //       }
  //       continue;
  //     }
  //     File file = File(filePath);
  //     Uint8List bytes = await file.readAsBytes();
  //     DioClient().uploadFromUint8List(filePath, bytes, hideLoading: hideLoading).then((value) => {
  //       if (value.isok) {
  //         prePaths.add(value.data),
  //         num++,
  //       }else{
  //         num++
  //       },
  //       if(num == filePaths.length){
  //         callBack(prePaths),
  //       }
  //     });
  //   }
  // }

  // Future<ResponseData> uploadFromUint8List(String fileName, Uint8List file, {bool hideLoading = false}) async {
  //   if (!hideLoading) {
  //     LoadingUtils.loading();
  //   }
  //   try {
  //     ResponseData response = await doGet("${ApiConfig.objectStorageUrl}/minio/presigned_upload_url",
  //         queryParameters: {
  //           "objectName": fileName,
  //         },
  //         options: Options(extra: {"hideLoading": true}));
  //     if (response.isok) {
  //       // 预下载成功的处理逻辑
  //       // 获取上传地址开始上传文件
  //       String uploadUrl = response.data;
  //       Stream<List<int>> stream = MultipartFile.fromBytes(file).finalize();
  //
  //       var upRes = await put(uploadUrl,
  //           data: stream, options: Options(headers: {'content-length': (file.lengthInBytes).toString()}, extra: {"hideLoading": true}));
  //
  //       if (upRes.statusCode == 200) {
  //         // 上传成功
  //         ResponseData downRes = await doGet("${ApiConfig.objectStorageUrl}/minio/presigned_download_url",
  //             queryParameters: {
  //               "objectName": fileName,
  //             },
  //             options: Options(extra: {"hideLoading": true}));
  //         if (!hideLoading) {
  //           LoadingUtils.dismiss();
  //         }
  //         return downRes;
  //       } else {
  //         ResponseData data = ResponseData.fromJson({'data': ""});
  //         data.isok = false;
  //         if (!hideLoading) {
  //           LoadingUtils.dismiss();
  //         }
  //         return data;
  //       }
  //     } else {
  //       if (!hideLoading) {
  //         LoadingUtils.dismiss();
  //       }
  //       return response;
  //     }
  //   } on Exception {
  //     ResponseData data = ResponseData.fromJson({'data': ""});
  //     data.isok = false;
  //     if (!hideLoading) {
  //       LoadingUtils.dismiss();
  //     }
  //     return data;
  //   }
  // }

  /// 请求类-----此处可以统一处理异常信息
  Future<T> _doRequest<T>(
    String path, {
    DioMethod method = DioMethod.get,
    Map<String, dynamic>? queryParameters,
    data,
    CancelToken? cancelToken,
    Options? options,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    const _methodValues = {
      DioMethod.get: 'get',
      DioMethod.post: 'post',
      DioMethod.put: 'put',
      DioMethod.delete: 'delete',
      DioMethod.patch: 'patch',
      DioMethod.head: 'head'
    };
    options ??= Options(method: _methodValues[method]);
    try {
      Response response;
      response = await request(path,
          data: data,
          queryParameters: queryParameters,
          cancelToken: cancelToken ?? _cancelToken,
          options: options,
          onSendProgress: onSendProgress,
          onReceiveProgress: onReceiveProgress);
      return response.data;
    } on DioError catch (e) {
      throw e;
    }
  }

  // //多个请求同时发送
  //
  // ///上传文件
  // uploadFile(formData) {
  //   var uploadOptions = Options(contentType: "multipart/form-data");
  //   return doPost(ApiConfig.uploadURL, options: uploadOptions, data: formData);
  // }

  ///代理抓包测试用
  void proxy() async {
    Map<String, String>? systemProxy = await SystemProxy.getProxySettings();

    if (systemProxy != null) {
      String? host = systemProxy["host"];
      String? port = systemProxy["port"];

      if (host?.isNotEmpty == true && port?.isNotEmpty == true) {
        (httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
            (client) {
          client.findProxy = (Uri uri) {
            return 'PROXY $host:$port';
          };
          client.badCertificateCallback =
              (X509Certificate cert, String host, int port) {
            return true;
          };
          return null;
        };
      }
    }

    // if (NetWorkConfig.proxyEnable) {
    //   if (NetWorkConfig.caughtAddress != "") {
    //     (httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
    //       client.findProxy = (Uri uri) {
    //         return 'PROXY ${NetWorkConfig.caughtAddress}';
    //       };
    //       client.badCertificateCallback = (X509Certificate cert, String host, int port) {
    //         return true;
    //       };
    //       return null;
    //     };
    //   }
    // }
  }

  /// 开启日志打印
  void openLog() {
    interceptors.add(LogInterceptor(responseBody: true));
  }

  /// 取消网络请求
  void cancelRequests({CancelToken? token}) {
    token ?? _cancelToken.cancel("cancelled");
  }

  ///   以下方法暂时用不到
  doGetUri<T>(
    Uri uri, {
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onReceiveProgress,
  }) {
    return getUri<T>(uri,
        options: options,
        cancelToken: cancelToken,
        onReceiveProgress: onReceiveProgress);
  }

  doPostUri<T>(
    Uri uri, {
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) {
    return postUri<T>(uri,
        options: options,
        cancelToken: cancelToken,
        onSendProgress: onSendProgress,
        onReceiveProgress: onReceiveProgress);
  }

  ///put请求
  doPut<T>(
    String path, {
    data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) {
    return put<T>(path,
        data: data,
        options: options,
        cancelToken: cancelToken,
        onSendProgress: onSendProgress,
        onReceiveProgress: onReceiveProgress);
  }
}
